/*
 * Created by Jaren at 2022/8/15 16:46
 */
import 'dart:math';
import 'dart:typed_data';
import 'package:inmotion_protocol/ezcan/util.dart';
import 'package:inmotion_protocol/util/byte_util.dart';

class V8V10LightEffectFileGenerator {
  static const formatSingleSide = 1;
  static const formatDoubleSize = 2;

  static const sizePeerColor = 3;

  static const channelCount = 4;
  static const column = 3;
  static const row = 7;

  /// 编辑器每帧灯珠数量
  static const editorLightCountPeerFrame = 42;

  /// 灯效文件（实际车上）的每帧灯珠个数
  /// 编辑时仅编辑一侧，生成灯效文件时需拷贝另一侧灯珠颜色
  static const lightCountPeerFrame = editorLightCountPeerFrame * 2;

  static Uint8ClampedList generate(int id, int frameCount, int interval, int relatedToSpeed, List<int> colors) {
    interval = interval ~/ 10;
    int frameSize = frameCount * lightCountPeerFrame * sizePeerColor;

    int totalLength = 4 + 1 + 1 + 1 + 1 + 1 + 1 + 4 + frameSize + 1;

    Uint8ClampedList bytes = Uint8ClampedList(totalLength);
    int offset = 0;

    /** HEAD START */
    ByteUtil.num2BytesLe(id, 4, bytes, offset);
    offset += 4;
    bytes[offset] = frameCount;
    offset++;
    bytes[offset] = interval;
    offset++;
    bytes[offset] = channelCount;
    offset++;
    bytes[offset] = column;
    offset++;
    bytes[offset] = row;
    offset++;
    bytes[offset] = relatedToSpeed;
    offset++;
    // reverse 4 bytes
    offset += 4;
    /** HEAD END */

    /** BODY START */
    Uint32List framesColors = reformatFrames(colors, frameCount);

    // 填充colors
    for (int i = 0; i < framesColors.length; i++) {
      ByteUtil.num2Bytes(correctColor(framesColors[i]), sizePeerColor, bytes, offset);
      offset += sizePeerColor;
    }
    /** BODY END */
    /** CHECK START */
    bytes[offset] = EzCANFileUtils.calculateSum(bytes, 0, bytes.length - 1);
    /** CHECK END */
    return bytes;
  }

  static Uint32List reformatFrames(List<int> framesColors, int frameCount) {
    List<int> formattedFramesColors = [];

    for (var i = 0; i < frameCount; i++) {
      int offset = i * editorLightCountPeerFrame;

      List<int> frameColors = resortSingleFrameColors(framesColors, offset);
      formattedFramesColors.addAll(frameColors);
      // 拷贝至另一侧
      formattedFramesColors.addAll(frameColors);
    }

    return Uint32List.fromList(formattedFramesColors);
  }

  static List<int> resortSingleFrameColors(List<int> colors, int offset) {
    List<int> resortedFrameColors = Int32List(editorLightCountPeerFrame);
    for (int i = 0; i < editorLightCountPeerFrame; i++) {
      if (i < 7 || (14 <= i && i < 21)) {
        // 0-6, 14-20
        resortedFrameColors[i] = colors[offset + 20 - i];
      } else if ((i < 14) || (28 <= i && i < 35)) {
        // 7-13, 28-34
        resortedFrameColors[i] = colors[offset + i];
      } else if (i < 28) {
        // 21-27, 35-41
        // 翻转
        resortedFrameColors[i] = colors[offset + 48 - i];
      } else if (i < 42) {
        // 35-41
        // 翻转
        resortedFrameColors[i] = colors[offset + 76 - i];
      }
    }
    return resortedFrameColors;
  }

  static int correctColor(int color) {
//        return Color
//            .fromARGB(0, _correctColorR(Color(color).red), _correctColorG(Color(color).green), _correctColorB(Color(color).blue))
//            .value;
    return color;
  }

  // 校正颜色
  static int _correctColorR(int r) {
    return (pow(r, 3) / 255) ~/ 255;
  }

  static int _correctColorG(int g) {
    return (pow(g, 3) / 255) ~/ 255;
  }

  static int _correctColorB(int b) {
    return (pow(b, 3) / 255) ~/ 255;
  }
}